#include <bwio.h>
#include <defs.h>
#include <user.h>

void NameServer();
void IdleTask();
void ClockServer();

typedef struct __delay_req {
  int delay;
  int num;
} delay_req;

void DelayClient() {
  delay_req request;
  delay_req reply;
  int tid = MyTid();
  int parent_tid;
  Receive(&parent_tid, NULL, 0);
  Reply(parent_tid, NULL, 0);

  bwprintf(COM2, "[%d] Client ID %d asking for delay data...\r\n", Time(), tid);
  Send(0, (char*)&request, sizeof(delay_req), (char*)&reply, sizeof(delay_req));
  int clock = WhoIs("clock-server");
  bwprintf(COM2, "[%d] Client ID %d got the clock server ID: %d.\r\n", Time(), tid, clock);
  
  int i;
  for (i = 0; i < reply.num; i++) {
    bwprintf(COM2, "[%d] Client ID %d delaying for %d ticks (#%d)...\r\n", Time(), tid, reply.delay, i + 1);
    Delay(reply.delay);
  }
  
  bwprintf(COM2, "[%d] Client ID %d exiting..\r\n", Time(), tid);
  Exit();
}

void UserInit() {
  // create required system tasks
  int i, client;
  int child;
  child = Create(8, &NameServer, "NameServer");
  Send(child, NULL, 0, NULL, 0);
  Create(0, &IdleTask, "IdleTask");
  child = Create(8, &ClockServer, "ClockServer");
  Send(child, NULL, 0, NULL, 0);
  
  // create the client tasks
  for (i = 0; i < 4; i++) {
    client = Create(6 - i, &DelayClient, "DelayClient");
    Send(child, NULL, 0, NULL, 0);
    bwprintf(COM2, "[%d] Created client ID %d and priority %d.\r\n", Time(), client, 6 - i);
  }
  
  for (i = 4; i < 8; i++) {
    int tid;
    delay_req request;
    delay_req reply;
    bwprintf(COM2, "[%d] 1st user task waits for client request #%d.\r\n", Time(), i - 3);
    Receive(&tid, (char*)&request, sizeof(delay_req));

    switch (tid) {
      case 5:
        reply.delay = 10;
        reply.num = 20;
        break;
      case 6:
        reply.delay = 23;
        reply.num = 9;        
        break;
      case 7:
        reply.delay = 33;
        reply.num = 6;
        break;
      case 8:
        reply.delay = 71;
        reply.num = 3;
        break;      
    }
    bwprintf(COM2, "[%d] 1st user replying to client ID %d.\r\n", Time(), tid);
    Reply(tid, (char*)&reply, sizeof(delay_req));
  }
  
  bwprintf(COM2, "[%d] 1st user exiting..\r\n", Time());
  Exit();
}
